﻿
// ## 苦竹 迁移 OSIN ##

//// Copyright (c) Microsoft. All rights reserved.
//// Licensed under the MIT license. See LICENSE file in the project root for full license information.

//using System;
//using System.Collections;
//using System.Collections.Specialized;
//using System.Text;

//namespace CuteAnt.Runtime
//{
//  //copied from System.Web.HttpUtility code (renamed here) to remove dependency on System.Web.dll
//  internal static class UrlUtility
//  {
//    #region ## 苦竹 屏蔽 ##
//    //private static Encoding s_asciiEncoding;

//    //private static Encoding AsciiEncoding
//    //{
//    //  get
//    //  {
//    //    if (s_asciiEncoding == null)
//    //    {
//    //      s_asciiEncoding = Encoding.GetEncoding("ascii");
//    //    }
//    //    return s_asciiEncoding;
//    //  }
//    //}
//    #endregion

//    //  Query string parsing support
//    public static NameValueCollection ParseQueryString(string query)
//    {
//      return ParseQueryString(query, Encoding.UTF8);
//    }

//    public static NameValueCollection ParseQueryString(string query, Encoding encoding)
//    {
//      if (query == null)
//      {
//        throw Fx.Exception.ArgumentNull("query");
//      }

//      if (encoding == null)
//      {
//        throw Fx.Exception.ArgumentNull("encoding");
//      }

//      if (query.Length > 0 && query[0] == '?')
//      {
//        query = query.Substring(1);
//      }

//      return new HttpValueCollection(query, encoding);
//    }

//    public static string UrlEncode(string str)
//    {
//      if (str == null)
//      {
//        return null;
//      }
//      return UrlEncode(str, Encoding.UTF8);
//    }

//    // URL encodes a path portion of a URL string and returns the encoded string.
//    public static string UrlPathEncode(string str)
//    {
//      if (str == null)
//      {
//        return null;
//      }

//      // recurse in case there is a query string
//      int i = str.IndexOf('?');
//      if (i >= 0)
//      {
//        return UrlPathEncode(str.Substring(0, i)) + str.Substring(i);
//      }

//      // encode DBCS characters and spaces only
//      return UrlEncodeSpaces(UrlEncodeNonAscii(str, Encoding.UTF8));
//    }

//    public static string UrlEncode(string str, Encoding encoding)
//    {
//      if (str == null)
//      {
//        return null;
//      }

//      #region ## 苦竹 修改 ##
//      //var bytes = UrlEncodeToBytes(str, encoding);
//      //return AsciiEncoding.GetString(bytes, 0, bytes.Length);
//      return Encoding.ASCII.GetString(UrlEncodeToBytes(str, encoding));
//      #endregion
//    }

//    public static string UrlEncodeUnicode(string str)
//    {
//      if (str == null)
//        return null;
//      return UrlEncodeUnicodeStringToStringInternal(str, false);
//    }

//    private static string UrlEncodeUnicodeStringToStringInternal(string s, bool ignoreAscii)
//    {
//      int l = s.Length;
//      StringBuilder sb = new StringBuilder(l);

//      for (int i = 0; i < l; i++)
//      {
//        char ch = s[i];

//        if ((ch & 0xff80) == 0)
//        {  // 7 bit?
//          if (ignoreAscii || IsSafe(ch))
//          {
//            sb.Append(ch);
//          }
//          else if (ch == ' ')
//          {
//            sb.Append('+');
//          }
//          else
//          {
//            sb.Append('%');
//            sb.Append(IntToHex((ch >> 4) & 0xf));
//            sb.Append(IntToHex((ch) & 0xf));
//          }
//        }
//        else
//        { // arbitrary Unicode?
//          sb.Append("%u");
//          sb.Append(IntToHex((ch >> 12) & 0xf));
//          sb.Append(IntToHex((ch >> 8) & 0xf));
//          sb.Append(IntToHex((ch >> 4) & 0xf));
//          sb.Append(IntToHex((ch) & 0xf));
//        }
//      }

//      return sb.ToString();
//    }

//    //  Helper to encode the non-ASCII url characters only
//    private static string UrlEncodeNonAscii(string str, Encoding e)
//    {
//      if (string.IsNullOrEmpty(str))
//      {
//        return str;
//      }
//      if (e == null)
//      {
//        e = Encoding.UTF8;
//      }
//      byte[] bytes = e.GetBytes(str);
//      bytes = UrlEncodeBytesToBytesInternalNonAscii(bytes, 0, bytes.Length, false);

//      #region ## 苦竹 修改 ##
//      //return AsciiEncoding.GetString(bytes, 0, bytes.Length);
//      return Encoding.ASCII.GetString(bytes);
//      #endregion
//    }

//    //  Helper to encode spaces only
//    private static string UrlEncodeSpaces(string str)
//    {
//      if (str != null && str.IndexOf(' ') >= 0)
//      {
//        str = str.Replace(" ", "%20");
//      }
//      return str;
//    }

//    public static byte[] UrlEncodeToBytes(string str, Encoding e)
//    {
//      if (str == null)
//      {
//        return null;
//      }
//      byte[] bytes = e.GetBytes(str);
//      return UrlEncodeBytesToBytesInternal(bytes, 0, bytes.Length, false);
//    }

//    public static string UrlDecode(string str, Encoding e)
//    {
//      if (str == null)
//      {
//        return null;
//      }
//      return UrlDecodeStringFromStringInternal(str, e);
//    }

//    //  Implementation for encoding
//    private static byte[] UrlEncodeBytesToBytesInternal(byte[] bytes, int offset, int count, bool alwaysCreateReturnValue)
//    {
//      int cSpaces = 0;
//      int cUnsafe = 0;

//      // count them first
//      for (int i = 0; i < count; i++)
//      {
//        char ch = (char)bytes[offset + i];

//        if (ch == ' ')
//        {
//          cSpaces++;
//        }
//        else if (!IsSafe(ch))
//        {
//          cUnsafe++;
//        }
//      }

//      // nothing to expand?
//      if (!alwaysCreateReturnValue && cSpaces == 0 && cUnsafe == 0)
//      {
//        return bytes;
//      }

//      // expand not 'safe' characters into %XX, spaces to +s
//      byte[] expandedBytes = new byte[count + cUnsafe * 2];
//      int pos = 0;

//      for (int i = 0; i < count; i++)
//      {
//        byte b = bytes[offset + i];
//        char ch = (char)b;

//        if (IsSafe(ch))
//        {
//          expandedBytes[pos++] = b;
//        }
//        else if (ch == ' ')
//        {
//          expandedBytes[pos++] = (byte)'+';
//        }
//        else
//        {
//          expandedBytes[pos++] = (byte)'%';
//          expandedBytes[pos++] = (byte)IntToHex((b >> 4) & 0xf);
//          expandedBytes[pos++] = (byte)IntToHex(b & 0x0f);
//        }
//      }

//      return expandedBytes;
//    }


//    private static bool IsNonAsciiByte(byte b)
//    {
//      return (b >= 0x7F || b < 0x20);
//    }

//    private static byte[] UrlEncodeBytesToBytesInternalNonAscii(byte[] bytes, int offset, int count, bool alwaysCreateReturnValue)
//    {
//      int cNonAscii = 0;

//      // count them first
//      for (int i = 0; i < count; i++)
//      {
//        if (IsNonAsciiByte(bytes[offset + i]))
//        {
//          cNonAscii++;
//        }
//      }

//      // nothing to expand?
//      if (!alwaysCreateReturnValue && cNonAscii == 0)
//      {
//        return bytes;
//      }

//      // expand not 'safe' characters into %XX, spaces to +s
//      byte[] expandedBytes = new byte[count + cNonAscii * 2];
//      int pos = 0;

//      for (int i = 0; i < count; i++)
//      {
//        byte b = bytes[offset + i];

//        if (IsNonAsciiByte(b))
//        {
//          expandedBytes[pos++] = (byte)'%';
//          expandedBytes[pos++] = (byte)IntToHex((b >> 4) & 0xf);
//          expandedBytes[pos++] = (byte)IntToHex(b & 0x0f);
//        }
//        else
//        {
//          expandedBytes[pos++] = b;
//        }
//      }

//      return expandedBytes;
//    }

//    private static string UrlDecodeStringFromStringInternal(string s, Encoding e)
//    {
//      int count = s.Length;
//      UrlDecoder helper = new UrlDecoder(count, e);

//      // go through the string's chars collapsing %XX and %uXXXX and
//      // appending each char as char, with exception of %XX constructs
//      // that are appended as bytes

//      for (int pos = 0; pos < count; pos++)
//      {
//        char ch = s[pos];

//        if (ch == '+')
//        {
//          ch = ' ';
//        }
//        else if (ch == '%' && pos < count - 2)
//        {
//          if (s[pos + 1] == 'u' && pos < count - 5)
//          {
//            int h1 = HexToInt(s[pos + 2]);
//            int h2 = HexToInt(s[pos + 3]);
//            int h3 = HexToInt(s[pos + 4]);
//            int h4 = HexToInt(s[pos + 5]);

//            if (h1 >= 0 && h2 >= 0 && h3 >= 0 && h4 >= 0)
//            {   // valid 4 hex chars
//              ch = (char)((h1 << 12) | (h2 << 8) | (h3 << 4) | h4);
//              pos += 5;

//              // only add as char
//              helper.AddChar(ch);
//              continue;
//            }
//          }
//          else
//          {
//            int h1 = HexToInt(s[pos + 1]);
//            int h2 = HexToInt(s[pos + 2]);

//            if (h1 >= 0 && h2 >= 0)
//            {     // valid 2 hex chars
//              byte b = (byte)((h1 << 4) | h2);
//              pos += 2;

//              // don't add as char
//              helper.AddByte(b);
//              continue;
//            }
//          }
//        }

//        if ((ch & 0xFF80) == 0)
//        {
//          helper.AddByte((byte)ch); // 7 bit have to go as bytes because of Unicode
//        }
//        else
//        {
//          helper.AddChar(ch);
//        }
//      }

//      return helper.GetString();
//    }

//    // Private helpers for URL encoding/decoding
//    private static int HexToInt(char h)
//    {
//      return (h >= '0' && h <= '9') ? h - '0' :
//      (h >= 'a' && h <= 'f') ? h - 'a' + 10 :
//      (h >= 'A' && h <= 'F') ? h - 'A' + 10 :
//      -1;
//    }

//    private static char IntToHex(int n)
//    {
//      //WCF CHANGE: CHANGED FROM Debug.Assert() to Fx.Assert()
//      Fx.Assert(n < 0x10, "n < 0x10");

//      if (n <= 9)
//      {
//        return (char)(n + (int)'0');
//      }
//      else
//      {
//        return (char)(n - 10 + (int)'a');
//      }
//    }

//    // Set of safe chars, from RFC 1738.4 minus '+'
//    internal static bool IsSafe(char ch)
//    {
//      if (ch >= 'a' && ch <= 'z' || ch >= 'A' && ch <= 'Z' || ch >= '0' && ch <= '9')
//      {
//        return true;
//      }

//      switch (ch)
//      {
//        case '-':
//        case '_':
//        case '.':
//        case '!':
//        case '*':
//        case '\'':
//        case '(':
//        case ')':
//          return true;
//      }

//      return false;
//    }

//    // Internal class to facilitate URL decoding -- keeps char buffer and byte buffer, allows appending of either chars or bytes
//    internal class UrlDecoder
//    {
//      private int _bufferSize;

//      // Accumulate characters in a special array
//      private int _numChars;
//      private char[] _charBuffer;

//      // Accumulate bytes for decoding into characters in a special array
//      private int _numBytes;
//      private byte[] _byteBuffer;

//      // Encoding to convert chars to bytes
//      private Encoding _encoding;

//      private void FlushBytes()
//      {
//        if (_numBytes > 0)
//        {
//          _numChars += _encoding.GetChars(_byteBuffer, 0, _numBytes, _charBuffer, _numChars);
//          _numBytes = 0;
//        }
//      }

//      internal UrlDecoder(int bufferSize, Encoding encoding)
//      {
//        _bufferSize = bufferSize;
//        _encoding = encoding;

//        _charBuffer = new char[bufferSize];
//        // byte buffer created on demand
//      }

//      internal void AddChar(char ch)
//      {
//        if (_numBytes > 0)
//        {
//          FlushBytes();
//        }

//        _charBuffer[_numChars++] = ch;
//      }

//      internal void AddByte(byte b)
//      {
//        // if there are no pending bytes treat 7 bit bytes as characters
//        // this optimization is temp disable as it doesn't work for some encodings

//        //if (_numBytes == 0 && ((b & 0x80) == 0)) {
//        //    AddChar((char)b);
//        //}
//        //else

//        {
//          if (_byteBuffer == null)
//          {
//            _byteBuffer = new byte[_bufferSize];
//          }

//          _byteBuffer[_numBytes++] = b;
//        }
//      }

//      internal string GetString()
//      {
//        if (_numBytes > 0)
//        {
//          FlushBytes();
//        }

//        if (_numChars > 0)
//        {
//          return new String(_charBuffer, 0, _numChars);
//        }
//        else
//        {
//          return string.Empty;
//        }
//      }
//    }

//    internal class HttpValueCollection : NameValueCollection
//    {
//      internal HttpValueCollection(string str, Encoding encoding)
//          : base(StringComparer.OrdinalIgnoreCase)
//      {
//        if (!string.IsNullOrEmpty(str))
//        {
//          FillFromString(str, true, encoding);
//        }

//        IsReadOnly = false;
//      }

//      internal void FillFromString(string s, bool urlencoded, Encoding encoding)
//      {
//        int l = (s != null) ? s.Length : 0;
//        int i = 0;

//        while (i < l)
//        {
//          // find next & while noting first = on the way (and if there are more)

//          int si = i;
//          int ti = -1;

//          while (i < l)
//          {
//            char ch = s[i];

//            if (ch == '=')
//            {
//              if (ti < 0)
//                ti = i;
//            }
//            else if (ch == '&')
//            {
//              break;
//            }

//            i++;
//          }

//          // extract the name / value pair

//          string name = null;
//          string value = null;

//          if (ti >= 0)
//          {
//            name = s.Substring(si, ti - si);
//            value = s.Substring(ti + 1, i - ti - 1);
//          }
//          else
//          {
//            value = s.Substring(si, i - si);
//          }

//          // add name / value pair to the collection

//          if (urlencoded)
//          {
//            base.Add(
//               UrlUtility.UrlDecode(name, encoding),
//               UrlUtility.UrlDecode(value, encoding));
//          }
//          else
//          {
//            base.Add(name, value);
//          }

//          // trailing '&'

//          if (i == l - 1 && s[i] == '&')
//          {
//            base.Add(null, string.Empty);
//          }

//          i++;
//        }
//      }

//      public override string ToString()
//      {
//        return ToString(true, null);
//      }

//      private string ToString(bool urlencoded, IDictionary excludeKeys)
//      {
//        int n = Count;
//        if (n == 0)
//          return string.Empty;

//        StringBuilder s = new StringBuilder();
//        string key, keyPrefix, item;

//        for (int i = 0; i < n; i++)
//        {
//          key = GetKey(i);

//          if (excludeKeys != null && key != null && excludeKeys[key] != null)
//          {
//            continue;
//          }
//          if (urlencoded)
//          {
//            key = UrlUtility.UrlEncodeUnicode(key);
//          }
//          keyPrefix = (!string.IsNullOrEmpty(key)) ? (key + "=") : string.Empty;

//          ArrayList values = (ArrayList)BaseGet(i);
//          int numValues = (values != null) ? values.Count : 0;

//          if (s.Length > 0)
//          {
//            s.Append('&');
//          }

//          if (numValues == 1)
//          {
//            s.Append(keyPrefix);
//            item = (string)values[0];
//            if (urlencoded)
//              item = UrlUtility.UrlEncodeUnicode(item);
//            s.Append(item);
//          }
//          else if (numValues == 0)
//          {
//            s.Append(keyPrefix);
//          }
//          else
//          {
//            for (int j = 0; j < numValues; j++)
//            {
//              if (j > 0)
//              {
//                s.Append('&');
//              }
//              s.Append(keyPrefix);
//              item = (string)values[j];
//              if (urlencoded)
//              {
//                item = UrlUtility.UrlEncodeUnicode(item);
//              }
//              s.Append(item);
//            }
//          }
//        }

//        return s.ToString();
//      }
//    }
//  }
//}
